package com.fibo.wechat;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;

/**
 * 发送微信公众号消息
 *
 * @author fibo
 * @since 2023-04-07
 */
@Component
public class SendMessageTask {

    /**
     * 早8点，晚10点发送
     */
    @Scheduled(cron = "0 0 8,22 * * ?")
    public void sendMessage() {
        // 日夜分割
        int hour = 18;
        // 接受用户id
        String openId = WeChat.toUser;
        // 模板id
        String templateId = "";
        // 消息模板的参数
        JSONObject data = new JSONObject();
        // 天气参数
        getWeather(data);
        // 网易云热评
        getReview(data);
        // 恋爱纪念日
        getLoveDay(data);
        // 生日提醒
        getBirthday(data);

        // 区分早晚模板，我这里设置了一个提醒字段，早晚的不一样
        String remindData = "";
        Calendar cal = Calendar.getInstance();
        int now = cal.get(Calendar.HOUR_OF_DAY);
        if (now < hour) {
            remindData = "白天记得想我~";
            templateId = WeChat.dayTemplate;
            getMorningHello(data);
        } else {
            remindData = "晚上要梦到我呀~";
            templateId = WeChat.nightTemplate;
            getEveningHello(data);
        }
        // 特别提醒
        JSONObject remindParam = new JSONObject();
        remindParam.put("value", remindData);
        remindParam.put("color", "#CC3333");
        data.put("remind", remindParam);

        // 发送模板消息的参数。参考resource目录下的param.json，data层里面的key都是消息模板的参数
        JSONObject param = new JSONObject();
        param.put("touser", openId);
        param.put("template_id", templateId);
        param.put("topcolor", "#009999");
        param.put("data", data);

        String token = getToken();
        String sendUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=";
        HttpResponse execute = HttpRequest.post(sendUrl + token)
                .header("Content-Type", "application/json; encoding=utf-8")
                .body(JSONObject.toJSONString(param))
                .execute();
        System.out.println(JSONObject.toJSONString(param));
        System.out.println(execute.toString());
    }

    /**
     * 获取天气信息
     */
    private void getWeather(JSONObject data) {
        String sn = CalSnUtil.calWeatherSn(Baidu.distinctId, Baidu.ak, Baidu.sk);
        String weatherUrl = "https://api.map.baidu.com/weather/v1/?district_id=" + Baidu.distinctId + "&data_type=all&ak=" + Baidu.ak + "&sn=" + sn;
        String weather = HttpUtil.get(weatherUrl, CharsetUtil.CHARSET_UTF_8);
        JSONObject weatherJson = JSONObject.parseObject(weather);
        JSONObject resultJson = weatherJson.getJSONObject("result");
        // 未来天气
        JSONArray forecasts = resultJson.getJSONArray("forecasts");
        // 第一条是当天天气
        JSONObject todayWeather = forecasts.getJSONObject(0);
        // 白天天气
        String textDay = todayWeather.getString("text_day");
        // 晚上天气
        String textNight = todayWeather.getString("text_night");
        // 最低气温
        String low = todayWeather.getString("low");
        // 最高气温
        String high = todayWeather.getString("high");
        // 风力
        String wcDay = todayWeather.getString("wc_day");
        // 风向
        String wdDay = todayWeather.getString("wd_day");
        // 日期
        String date = todayWeather.getString("date");
        // 周几
        String week = todayWeather.getString("week");

        // 天气做个拼接
        String dateData = date + " " + week;
        String weatherData = "白天" + textDay + ",夜晚" + textNight;
        String tempData = low + "~" + high + "℃";
        String windData = wdDay + " " + wcDay;

        // 设置Jason参数
        JSONObject dateParam = new JSONObject();
        dateParam.put("value", dateData);
        dateParam.put("color", "#006699");
        data.put("date", dateParam);

        JSONObject weatherParam = new JSONObject();
        weatherParam.put("value", weatherData);
        weatherParam.put("color", "#FF9933");
        data.put("weather", weatherParam);

        JSONObject tempParam = new JSONObject();
        tempParam.put("value", tempData);
        tempParam.put("color", "#333399");
        data.put("temp", tempParam);

        JSONObject windParam = new JSONObject();
        windParam.put("value", windData);
        windParam.put("color", "#99CC00");
        data.put("wind", windParam);
    }

    /**
     * 获取网易热评
     */
    private void getReview(JSONObject data) {
        String hotReviewUrl = "https://apis.tianapi.com/hotreview/index?key=" + TiApi.key;
        String hotReview = HttpUtil.get(hotReviewUrl, CharsetUtil.CHARSET_UTF_8);
        JSONObject hotReviewJson = JSONObject.parseObject(hotReview);
        JSONObject reviewResult = hotReviewJson.getJSONObject("result");
        String reviewContent = reviewResult.getString("content");
        String reviewSource = reviewResult.getString("source");

        String reviewData = reviewContent + "  --《" + reviewSource + "》";
        JSONObject reviewParam = new JSONObject();
        reviewParam.put("value", reviewData);
        reviewParam.put("color", "#99CC33");
        data.put("review", reviewParam);
    }

    /**
     * 获取早安心语
     */
    private void getMorningHello(JSONObject data) {
        String morningUrl = "https://apis.tianapi.com/zaoan/index?key=" + TiApi.key;
        String morning = HttpUtil.get(morningUrl, CharsetUtil.CHARSET_UTF_8);
        JSONObject morningJson = JSONObject.parseObject(morning);
        JSONObject morningResult = morningJson.getJSONObject("result");
        String helleData = morningResult.getString("content");

        JSONObject helloParam = new JSONObject();
        helloParam.put("value", helleData);
        helloParam.put("color", "#33CC99");
        data.put("hello", helloParam);
    }

    /**
     * 获取晚安心语
     */
    private void getEveningHello(JSONObject data) {
        String eveningUrl = "https://apis.tianapi.com/wanan/index?key=45f52ec381d92a35bc6b4fa4f38d394e";
        String evening = HttpUtil.get(eveningUrl, CharsetUtil.CHARSET_UTF_8);
        JSONObject eveningJson = JSONObject.parseObject(evening);
        JSONObject eveningResult = eveningJson.getJSONObject("result");
        String helleData = eveningResult.getString("content");

        JSONObject helloParam = new JSONObject();
        helloParam.put("value", helleData);
        helloParam.put("color", "#33CC99");
        data.put("hello", helloParam);
    }

    /**
     * 设置恋爱时间
     */
    private void getLoveDay(JSONObject data) {
        int loveData = getDayDiff();
        JSONObject loveDay = new JSONObject();
        loveDay.put("value", loveData);
        loveDay.put("color", "#33CC99");
        data.put("loveDay", loveDay);
    }

    /**
     * 获取生日倒计时
     */
    private void getBirthday(JSONObject data) {
        long birthData = getRemainDay();
        JSONObject birthday = new JSONObject();
        birthday.put("value", birthData);
        birthday.put("color", "#33CC99");
        data.put("birthday", birthday);
    }

    /**
     * 现在和纪念日相差天数
     */
    private int getDayDiff() {
        String s1 = DateSet.loveDay;
        // 指定日期格式
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 按照指定格式转化为LocalDate对象
        LocalDate time1 = LocalDate.parse(s1, dateTimeFormatter);
        LocalDate time2 = LocalDate.now();
        // 调方法计算两个LocalDate的天数差
        long between = ChronoUnit.DAYS.between(time1, time2) + 1;
        return (int) between;
    }

    /**
     * 计算生日倒计时
     */
    private long getRemainDay() {
        int dayMill = 86400000;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        Date now = new Date();
        String year = sdf.format(now);
        String dateStr = year + "-" + DateSet.birthday;
        SimpleDateFormat parseSdf = new SimpleDateFormat("yyyy-MM-dd");
        Date time = null;
        try {
            time = parseSdf.parse(dateStr);
        } catch (Exception e) {
            return 0;
        }
        long diff = time.getTime() - now.getTime();
        long day = diff / dayMill;
        if (day < 0) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(time);
            calendar.add(Calendar.YEAR, 1);
            diff = calendar.getTimeInMillis() - now.getTime();
            day = diff / dayMill;
        }
        return day;
    }

    /**
     * 获取微信api的token
     */
    private String getToken() {
        String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + WeChat.appid + "&secret=" + WeChat.secret;
        String tokenResp = HttpUtil.get(tokenUrl);
        JSONObject tokenJson = JSONObject.parseObject(tokenResp);
        return tokenJson.getString("access_token");
    }

    /**
     * 纪念日参数
     */
    static class DateSet {

        /**
         * 在一起的日期 按格式写
         * TODO 替换
         */
        public static String loveDay = "2023-01-01";

        /**
         * 生日 按格式写
         * TODO 替换
         */
        public static String birthday = "03-07";
    }

    /**
     * 微信测试号
     * <a href="https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index">测试号地址</a>
     * 替换成自己微信测试号的appid和secret
     */
    static class WeChat {

        /**
         * 测试号的appID
         * TODO 替换
         */
        public static String appid = "";

        /**
         * 测试号的appsecret
         * TODO 替换
         */
        public static String secret = "";

        /**
         * 接受用户id
         * TODO 替换
         */
        public static String toUser = "";

        /**
         * 白天模板id
         * TODO 替换
         */
        public static String dayTemplate = "";

        /**
         * 晚上模板id
         * TODO 替换
         */
        public static String nightTemplate = "";
    }

    /**
     * 天行api 的 ak
     * 替换成自己天行api的ak
     */
    static class TiApi {

        /**
         * TODO 替换
         */
        public static String key = "";
    }

    /**
     * 百度参数
     * 替换成自己百度账号的 ak和sk
     */
    static class Baidu {
        /**
         * 区域id
         * <a href="https://lbsyun.baidu.com/index.php?title=webapi/weather">查看区域代码</a>
         * TODO 替换
         */
        public static String distinctId = "330106";

        /**
         * 百度应用的ak
         * TODO 替换
         */
        public static String ak = "";

        /**
         * 百度应用的sk
         * TODO 替换
         */
        public static String sk = "";
    }
}
